#include "TCPServerChannel.h"
#include "TCPServerWrapper.h"

namespace network
{

TCPServerWrapper::TCPServerWrapper()
{
}

TCPServerWrapper::TCPServerWrapper(UInt16 port)
: _nPort(port)
{
}

TCPServerWrapper::~TCPServerWrapper()
{
}

bool TCPServerWrapper::start(UInt16 port)
{
	if (port == (UInt16)-1 && _nPort == (UInt16)-1)
		return false;

	if (port != (UInt16)-1)
		_nPort = port;

	ServerSocket serverSock(_nPort);
	if (_poTCPServer == nullptr)
	{
		_poTCPServer = new TCPServer(new TCPServerConnectionFactoryWrapper(_vecChannels), serverSock);
	}

	_poTCPServer->start();

	_vecChannels.clear();

	return true;
}

bool TCPServerWrapper::stop()
{
	if (_poTCPServer != nullptr)
	{
		_poTCPServer->stop();
		delete _poTCPServer;
	}

	while (_vecChannels.size() > 0)
	{
		_vecChannels.back()->cancel();
		_vecChannels.pop_back();
	}

	_vecChannels.clear();

	return true;
}

TCPServerChannel::Ptr TCPServerWrapper::registChannel(std::string& name, std::function<void(const TCPServerDispatcherPacket::Ptr&)> handlePacket)
{
	UInt32 nChID = getFreeChannelID();

	TCPServerChannel::Ptr channel = new TCPServerChannel(name, nChID, handlePacket);

	_vecChannels[nChID] = channel;
	_mapChannelIDs[name] = nChID;

	channel->run();

	return channel;
}

void TCPServerWrapper::unregistChannel(std::string& name)
{
	if (_mapChannelIDs.find(name) == _mapChannelIDs.end())
		return;

	UInt32 id = _mapChannelIDs[name];
	_vecChannels[id]->cancel();

	auto itr = _vecChannels.begin();
	UInt32 i = 0;
	for (; itr != _vecChannels.end(); ++itr)
	{
		if (i == id)
		{
			_vecChannels.erase(itr);
			break;
		}
		++i;
	}
}

UInt32 TCPServerWrapper::getFreeChannelID()
{
	UInt32 i = 0;

	for (i = 0; i < _vecChannels.size(); i++)
	{
		if (_vecChannels[i].isNull())
			break;
	}

	if (i == _vecChannels.size())
		throw new Poco::PoolOverflowException("TCPServer Channel count overflow.");
	else
		return i;
}

}
